


#include <boost/bind.hpp>

#include "CxIPService.h"
#include "CxTcpPort.h"

using namespace ImitateTansfer;


CxTcpPort::CxTcpPort():m_psocket(new tcp::socket(CxIPService::s_ioservice)),m_portno(0)
{
}


CxTcpPort::CxTcpPort(tcp::socket *sock,UINT	portno):m_psocket(sock),m_portno(portno)
{
}


CxTcpPort::~CxTcpPort()
{
	ClosePort();
}


bool	CxTcpPort::OpenPort(LPCSTR		portname)
{
	CX_ASSERT(portname);
	return true;
}


inline	bool	CxTcpPort::ClosePort()
{
	if(m_psocket==NULL)return true;
	CX_ASSERT(m_psocket);
	m_psocket->close();
	delete m_psocket;
	m_psocket=NULL;	
}


inline	bool	CxTcpPort::IsOpen()const
{
	if(m_psocket==NULL)return false;
	return m_psocket->is_open();
}


inline	UINT	CxTcpPort::GetStatus()const
{
	return 0;
}


size_t	CxTcpPort::ReadPort(BYTE *_buffer,size_t size)
{
	if(!m_psocket->is_open())return 0;
	boost::system::error_code	e;

	return m_psocket->read_some(boost::asio::buffer(_buffer,size),e);	

	if(e)
	{
		ClosePort();
		sig_close();
	}
}

size_t	CxTcpPort::ReadPort(BYTE *_buffer,size_t size,
	const boost::function<void (const boost::system::error_code& error ,size_t bytes_transferred) > &rtfunc)
{
	if(!m_psocket->is_open())return 0;

	//Òì²½¶ÁÈ¡¶Ë¿Ú£¬´«ÈëÍê³É»Øµ÷º¯Êý¶ÁÈ¡Íê±Ïºóµ÷ÓÃ
	m_psocket->async_read_some(boost::asio::buffer(_buffer,size),rtfunc);
}

size_t	CxTcpPort::WritePort(BYTE *_buffer,size_t size)
{
	if(!m_psocket->is_open())return 0;

	//Òì²½Ð´Èë¶Ë¿Ú
	//m_psocket->async_write_some(boost::asio::buffer(_buffer,size),
	//	boost::bind<void>(&CxTcpPort::CallBackHandler,_buffer));
	try
	{
		m_psocket->write_some(boost::asio::buffer(_buffer,size));
	}
	catch(const boost::system::system_error &e)
	{
		m_psocket->close();
		sig_close();
	}


}



//////////////////////////////////////////////////////////////////////////////////////////
/*
*		ÒÔÏÂÎªµ÷ÊÔ´úÂë£¬²âÊÔÍ¼Æ¬Êý¾ÝÔÚ·¢ËÍÇ°ÊÇ·ñÍêÕû
*/
////////////////////////////////////////////////////////////////////////////////////////////
#ifdef __CXDEBUG
#include <opencv2\opencv.hpp>
#include <zlib.h>

void SaveImage (CxPackage *pack)
{
	char *data=pack->GetData();
	int  height;
	int  width;
	short  depth;

	height=(*(int *)&data[2]);
	width=(*(int *)&data[6]);
	depth=(*(short*)&data[10]);

	unsigned long size=(*(unsigned long *)&data[12]);

	char *imgdata=&data[16];

	char *rtdata=new char [3*size];
	unsigned long rtsize=3*size;
	uncompress((unsigned char*)rtdata,&rtsize,(unsigned char*)imgdata,size);
	CvSize _cvsize;
	_cvsize.height=height;
	_cvsize.width=width;
	

	IplImage *pimage=cvCreateImage(_cvsize,depth,3);
	memcpy(pimage->imageData,rtdata,rtsize);

	cvSaveImage("E:\\Files\\02.jpg",pimage);
	
	cvReleaseImage(&pimage);
}

#endif
////////////////////////////////////////////////////////////////////////////////////////////
/*
*			ÒÔÉÏÎªµ÷ÊÔ´úÂë£¬²âÊÔÍ¼Æ¬Êý¾ÝÔÚ·¢ËÍÇ°ÊÇ·ñÍêÕû
*/
////////////////////////////////////////////////////////////////////////////////////////////

size_t CxTcpPort::WritePort(CxPackage *pack)
{
	if(!m_psocket->is_open())return 0;

	//ÊÔÑéº¯Êý£¬²é¿´·¢ËÍÊ±Êý¾ÝÍêÕûÐÔ
	//SaveImage(pack);

	char  rtbuffer[5];

	//Òì²½Ð´Èë¶Ë¿Ú
	//½«Êý¾ÝÒ»´ÎÐÔ·¢ËÍÍê±Ï£¬Íê³Éºóµ÷ÓÃ»Øµ÷º¯ÊýÇå³ýbuffer
	m_psocket->async_write_some(boost::asio::buffer(pack->GetData(),pack->GetDataSize()),
                                boost::bind<void>	(&CxTcpPort::CallBackHandler_Pack,
													boost::asio::placeholders::error,				//±ê×¼³ö´í
													boost::asio::placeholders::bytes_transferred,	//´«µÝÊýÖµ
													m_psocket,
													pack,											//´«µÝµÄ°ü
													this
													)
                                );
								



    return 0;
}

void		CxTcpPort::CallBackHandler_Pack(	const boost::system::error_code &e,
											std::size_t size,
											tcp::socket *psock,
											CxPackage	*_buffer,
											CxPort		*port
											)
{
    if(e)
    {
        if(psock->is_open())
        {
            psock->cancel();
            psock->close();
			port->sig_close();
        }

        switch(e.value())
        {
            case boost::asio::error::connection_reset:
                CX_ERR_MESSAGE("Connect Refuse.....");
                break;

            case boost::asio::error::connection_aborted:
                CX_ERR_MESSAGE("Connect Abort.....");
                break;

            case boost::asio::error::connection_refused:
                CX_ERR_MESSAGE("Connect Refuse.....");
                break;
            case boost::asio::error::no_buffer_space:
                CX_ERR_MESSAGE("No Buffer.....");
                break;
            default:
                CX_ERR_MESSAGE(e.message());
                break;
        }
    }

    if(size != _buffer->GetDataSize())
    {
        CX_ERR_MESSAGE("The Send Data size is not match....");
    }

	if(_buffer!=NULL)
	{
		delete _buffer;
	}
}

